package util.text;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class URLParser {
    protected byte type;
    protected static final byte TYPE_URL          = 1;
    protected static final byte TYPE_QUERY_STRING = 2;

    protected String url;
    protected String queryString;
    protected String charset = "utf-8";


    protected boolean compiled = false;
    protected Map<String, String> parsedParams;

    protected URLDecoder urld = new URLDecoder();

    protected URLParser() {
    }

    public static URLParser fromURL(String url) {
        URLParser parser = new URLParser();

        parser.type = TYPE_URL;
        parser.url = url;

        String[] split = url.split("\\?", 2);
        parser.queryString = split.length > 1 ? split[1] : "";

        return (parser);
    }

    public static URLParser fromQueryString(String queryString) {
        URLParser parser = new URLParser();

        parser.type = TYPE_QUERY_STRING;
        parser.queryString = queryString;

        return (parser);
    }

    public URLParser useCharset(String charset) {
        this.charset = charset;
        return (this);
    }

    /**
     * Parse and cache results, improve performance while re-used.
     */
    public URLParser compile()
            throws UnsupportedEncodingException {
        String paramString = this.queryString.split("#")[0];
        String[] params = paramString.split("&");

        this.parsedParams = new HashMap<String, String>(params.length);
        for (String p : params) {
            String[] kv = p.split("=");
            if (kv.length == 2) {
                this.parsedParams.put(kv[0], this.urld.decode(kv[1], this.charset));
            }
        }

        this.compiled = true;

        return (this);
    }

    public String getParameter(String name) {
        if (this.compiled) {
            return (this.parsedParams.get(name));
        }

        String paramString = this.queryString.split("#")[0];
        Matcher match = Pattern.compile("(^|&)" + name + "=([^&]*)").matcher(paramString);
        match.lookingAt();

        return (match.group(2));
    }


    public static void main(String[] args) {
        try {
            System.out.println(
                    URLParser.fromURL(
                            "https://www.google.com/search?q=test&hl=zh_cn&oq=test&gs_l=heirloom-serp.3...38011332.38012012.0.38012235.4.4.0.0.0.0.0.0..0.0.msedr...0...1ac.1.34.heirloom-serp..4.0.0.1q6YK2r8vHI"
                    ).getParameter("q")
            );
            System.out.println(
                    URLParser.fromURL(
                            "https://www.google.com/search?q=test&hl=zh_cn&oq=test&gs_l=heirloom-serp.3...38011332.38012012.0.38012235.4.4.0.0.0.0.0.0..0.0.msedr...0...1ac.1.34.heirloom-serp..4.0.0.1q6YK2r8vHI"
                    ).compile()
                            .getParameter("q")
            );
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
